package stateDiagram;

import static org.jhotdraw.draw.AttributeKeys.FILL_COLOR;

import java.awt.Color;
import java.util.ArrayList;
import java.util.IllegalFormatException;
import java.util.IllformedLocaleException;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import javax.naming.directory.InvalidAttributeValueException;
import javax.swing.JOptionPane;

import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.GraphicalCompositeFigure;

import stateDiagram.EntityObjects.StateEntity;
import stateDiagram.EntityObjects.TransitionEntity;
import stateDiagram.figures.EndStateFigure;
import stateDiagram.figures.StartStateFigure;
import stateDiagram.figures.StateFigure;
import stateDiagram.figures.TransitionFigure;

public class ErrorChecker 
{
	List<Figure> allFigures;
	List<Figure> states;
	List<TransitionEntity> transitions;
	static List<Figure> errorCheck;
	StateEntity currentState;
	boolean foundStart = false;
	boolean foundEnd = false;
	StartStateFigure start = null;
	EndStateFigure end = null;
	
	public void checkForErrors(Drawing toCheck)
	{	
		//Create lists of all figures
		List<Figure> allFigures = toCheck.getChildren();
		states = new ArrayList<Figure>();
		transitions = new ArrayList<TransitionEntity>();
		
		Iterator<Figure> it = allFigures.iterator();
		while (it.hasNext()){
			Figure f = it.next();
			if (f != null)
				if (f instanceof StateFigure)
					states.add(f);
				else 
				{
					if (f instanceof TransitionEntity)
					{
						transitions.add((TransitionEntity)f);
					}
					else
					{
						if ( f instanceof StartStateFigure )
						{
							start = (StartStateFigure) f;
							states.add(f);// you iterate through states looking for this below but you never added it.-jm
						}
						else
						{
							if (f instanceof EndStateFigure)
							{
								end = (EndStateFigure) f;
								states.add(f);//same here.. -james
							}
						}
					}
				}
		}
		
		//RESET COLOR / TEXT OF ALL STATES TO DEFAULT- don't do that it fucks up the colors on everything - james
		/*for (Figure fx : allFigures)                //change the color of the bad ones if you want to change colors
		{
			fx.set(FILL_COLOR, null);
		}*/
		
		//check that:
		//all states are reachable ie: there is a transition into every state that is not the start state
		//there exists one and only one start and end state
		//there are no duplicate transitions
		//all states have unique names
		//change all good states to their default color upon initial collection / iteration

		try
		{
			//Look for singleton start state
			resetList();
			for (Figure statex : states)
			{
				if (statex instanceof StartStateFigure)
				{
					errorCheck.add(statex);
					foundStart = true;
					start = (StartStateFigure) statex;
				}
			}
			if (start == null) throw new NoSuchElementException(); 
			if (errorCheck.size() > 1) throw new IllegalArgumentException();
			
			//Look for singleton end state
			resetList();
			errorCheck.clear();// empty the list to remove start state so the checks below work -jm
			for (Figure statex : states)
			{
				if (statex instanceof EndStateFigure)
				{
					errorCheck.add(statex);
					foundEnd = true;
					end = (EndStateFigure) statex;
				}
			}
			if (errorCheck.isEmpty()) throw new NoSuchElementException();
			if (errorCheck.size() > 1) throw new IllegalArgumentException();
			
			
			//Check that each state is reachable
			resetList();
			//create a copy of transitions
			for (Figure sx : states)
			{
				errorCheck.add((Figure) sx);
			}
			for (TransitionEntity transx : transitions)
			{
				if (errorCheck.contains(transx.getNextState()))
				{
					errorCheck.remove(transx);
				}
			}
			if (!errorCheck.isEmpty())
			{
				throw new IllegalStateException();
			}
			
			//Check that all states have unique names
			ArrayList<String> name = new ArrayList<String>();
			for (Figure statex : states)
			{
				name.add(((StateEntity) statex).getName());
			}
			for (String namex : name)
			{
				resetList();
				int i = 0;
				for (Figure statex : states)
				{
					if (name.equals(((StateEntity)(statex)).getName()))
					{
						errorCheck.add(statex);
					}
				}
				if (errorCheck.size() > 1)
				{
					throw new InvalidAttributeValueException();
				}
			}
			
			//check that there exist no duplicate transitions within a state
			resetList();
			
			for (TransitionEntity tx : transitions)
			{
				int count = 0;
				resetList();
				for (TransitionEntity txInner : transitions)
				{
					if (txInner.equals(tx))
					{
						++count;
						errorCheck.add((Figure) tx);
					}
				}
				if (count > 1)
				{
					throw new IllformedLocaleException();
				}
			}
			
			
			
			
		}
		catch(NoSuchElementException e)
		{
			if (!foundStart) //No start state
			{
				display("No Start State found in this drawing! Could not enter!");
			}
			else 
			{
				if (!foundEnd) //No End state 
				{
					display("No End State Found!");
				}
				else //Anything else/?
				{
					
				}
			}
		}
		catch(IllegalArgumentException e) //Multiple start or end states
		{
			if (foundStart && foundEnd) //end state duplicate
			{
				display("Too many end states were found! You may only have one end state!");
				for (Figure endx : errorCheck)
				{
					//change color of all duplicates to red
					endx.set(FILL_COLOR, Color.RED);
					System.out.println(endx.toString());
				}
			}
			else //start state duplicate
			{
				display("Too many start states were found! You may only have one start state!");
				for (Figure startx : errorCheck)
				{
					System.out.println(startx.toString());
					//change color of all duplicates to red
					startx.set(FILL_COLOR, Color.RED);
				}
			}
		}
		catch(IllegalStateException e)
		{
			display("One or more states are not reachable!!");
			for (Figure fx : errorCheck)
			{
				//change color of all remaining states in errorCheck to red
				fx.set(FILL_COLOR, Color.RED);
			}
			for (Figure fx : errorCheck)
			{
				System.out.println(((TransitionEntity) fx).toString());
			}
		}
		catch(InvalidAttributeValueException e)
		{
			display("There exist duplicate state names, state names must be unique!");
			for (Figure fx : errorCheck)
			{
				System.out.println(((StateEntity)fx).getName());
			}
		}
		catch(IllformedLocaleException e)
		{
			//change all transitions to have red names??
			display("There cannot exist duplicate transitions in a state");
			for (Figure fx : errorCheck)
			{
				fx.set(FILL_COLOR, Color.RED);
				System.out.println(((TransitionEntity) fx).toString());
			}
		}
		return;
	}
	public static void resetList()
	{
		errorCheck = new ArrayList<Figure>();
	}
	private static void display(String message){
		JOptionPane.showMessageDialog(null,message);
	}
	
	
}
